﻿using Microsoft.Practices.Unity.Configuration;
using rmTest.Common.UnityUtil;
using rmTest_EfIocAof.Interface;
using rmTest_EfIocAof.Service;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Unity;
using Unity.Lifetime;

namespace IocTest
{
    public class IocTestShow
    {
        public static void Show()
        {
            {
                Console.WriteLine("***************Unity容器的基础应用*****************");
                IUnityContainer unityContainer = new UnityContainer();//声明一个容器
                unityContainer.RegisterType<IPhone, ApplePhone>();//初始化容器 注册类型
                //container.RegisterType<IPhone, ApplePhone>(new TransientLifetimeManager());//默认  瞬时  每一次都是全新生成
                unityContainer.RegisterType<IEarPhone, EarPhone>();//对应依赖的类型也需要注册
                IPhone iPhone = unityContainer.Resolve<IPhone>();//反射创建对象
                iPhone.Call();

                unityContainer.RegisterType<AbstractPad, ApplePad>();//unityContainer.RegisterType<AbstractPad, ApplePad>("ApplePad")
                unityContainer.RegisterType<AbstractPad, MiniApplePad>();//初始化容器，注册类型是覆盖式的，解决方式：起一个名字

                AbstractPad iPad = unityContainer.Resolve<AbstractPad>();//MiniApplePad

                var phone1 = unityContainer.Resolve<IPhone>();
                var phone2 = unityContainer.Resolve<IPhone>();
                Console.WriteLine(object.ReferenceEquals(phone1, phone2));//比较两个引用类型是否指向同一块内存，False，瞬时生命周期
            }
            {
                Console.WriteLine("***************Unity容器的基础应用*****************");
                IUnityContainer container = new UnityContainer();//声明一个容器
                container.RegisterType<IPhone, ApplePhone>(new PerThreadLifetimeManager());//初始化容器 注册类型
                container.RegisterType<IEarPhone, EarPhone>(new PerThreadLifetimeManager());//线程单例：相同线程的实例相同 不同线程的实例不同   web请求 / 多线程操作

                //container.RegisterType<IEarPhone, EarPhone>(new ContainerControlledLifetimeManager());//容器单例  单例就不要自己实现
                //TransientLifetimeManager                  默认  瞬时  每一次都是全新生成
                //PerThreadLifetimeManager                  线程单例：相同线程的实例相同 不同线程的实例不同   web请求/多线程操作
                //ContainerControlledLifetimeManager        容器单例  单例就不要自己实现
                //HierarchicalLifetimeManager               分级容器单例
                //ExternallyControlledLifetimeManager       外部可释放单例  单例是全局唯一；一旦释放大家都没了；
                //PerResolveLifetimeManager                 //循环引用 不推荐
                IPhone iphone1 = null;
                Action act1 = new Action(() =>
                {
                    iphone1 = container.Resolve<IPhone>();
                    Console.WriteLine($"iphone1由线程id={Thread.CurrentThread.ManagedThreadId}");
                });
                var result1 = act1.BeginInvoke(null, null);

                IPhone iphone2 = null;
                Action act2 = new Action(() =>
                {
                    iphone2 = container.Resolve<IPhone>();
                    Console.WriteLine($"iphone2由线程id={Thread.CurrentThread.ManagedThreadId}");
                });

                IPhone iphone3 = null;
                var result2 = act2.BeginInvoke(t =>
                {
                    iphone3 = container.Resolve<IPhone>();
                    Console.WriteLine($"iphone3由线程id={Thread.CurrentThread.ManagedThreadId}");
                    Console.WriteLine($"object.ReferenceEquals(iphone2, iphone3)={object.ReferenceEquals(iphone2, iphone3)}");
                }, null);

                act1.EndInvoke(result1);
                act2.EndInvoke(result2);

                Console.WriteLine($"object.ReferenceEquals(iphone1, iphone2)={object.ReferenceEquals(iphone1, iphone2)}");//False 
            }
            Console.WriteLine("*****************Unity热插拔扩展*********************");
            {
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");//找配置文件的路径
                Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);

                IUnityContainer container = new UnityContainer();
                section.Configure(container, "testContainer");
                IPhone phone = container.Resolve<IPhone>();
                phone.Call();

                IPhone android = container.Resolve<IPhone>("Android");
                android.Call();

                //不通过引用项目，只通过配置config和bin中添加dll，完成对象的构建
                IPhone extendandroid = container.Resolve<IPhone>("ExtendAndroid");
                extendandroid.Call();
            }
            Console.WriteLine("*****************Unity热插拔扩展+AOP*********************");
            {
                IUnityContainer container = UnityContext.GetInstance("CfgFiles\\Unity.Config", "testContainerAop");

                //不通过引用项目，只通过配置config和bin中添加dll，完成对象的构建
                IPhone extendandroid = container.Resolve<IPhone>("ExtendAndroid");
                extendandroid.Call();
            }
            {

                //Console.WriteLine("***************Unity容器的基础应用2*****************");
                //IUnityContainer unityContainer = new UnityContainer();//声明一个容器
                //unityContainer.RegisterType<IPhone, ApplePhone>();//初始化容器 注册类型
                //IPhone iPhone = unityContainer.Resolve<IPhone>();//反射创建对象
                //iPhone.Call();

                //unityContainer.RegisterType<AbstractPad, ApplePad>();
                //unityContainer.RegisterType<ApplePad, MiniApplePad>();//初始化容器，注册类型是覆盖式的，ApplePad 也是IPad

                //AbstractPad iPad = unityContainer.Resolve<AbstractPad>();//MiniApplePad
            }
        }
    }
}
